'use client';

import type { IDraft, IPostEditInfo, IPostNewInfo } from '@/interfaces';
import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query';
import {
  queryDraft,
  queryEditPostDrafts,
  queryPostDrafts,
  removeDraft,
} from '@/services/api';
import Alert from '@/app/[locale]/alert/alert';
import AlertLoad from '@/app/[locale]/alert/load';
import type { TBody } from '@/types';
import classNames from 'classnames';
import { type Dispatch, type SetStateAction, useState } from 'react';
import { formatTime } from '@/lib/tool';
import useToast from '@/hooks/useToast';
import { type QueryKey } from '@tanstack/query-core';
import { useTranslations } from 'use-intl';

export default function Draft(
  this: any,
  {
    isEdit = true,
    data,
    hideModal,
    setData,
  }: {
    isEdit?: boolean;
    data: IPostNewInfo | IPostEditInfo;
    hideModal: () => void;
    setData: (value: any) => void;
  },
) {
  const t = useTranslations('PostEditPage');
  const [currentItemId, setCurrentItemId] = useState<number>();
  const [currentItem, setCurrentItem] = useState<IDraft>();
  const newPostQueryKey = ['/forum', '/drafts', '/posts', '/new'];
  const editPostQueryKey = [
    '/forum',
    '/drafts',
    '/posts',
    isEdit ? (data as IPostEditInfo).basic.id : undefined,
    '/edit',
  ];

  const queryNewPostDraftsQuery = useQuery(
    newPostQueryKey,
    async () => {
      return (await queryPostDrafts()) as IDraft[];
    },
    {
      enabled: !isEdit,
    },
  );
  const queryEditPostDraftsQuery = useQuery(
    editPostQueryKey,
    async (context) => {
      return (await queryEditPostDrafts({
        id: context.queryKey[3] + '',
      })) as IDraft[];
    },
    {
      enabled: isEdit,
    },
  );

  function onClickItem(item: IDraft) {
    setCurrentItem(item);
    setCurrentItemId(item.id);
  }

  if (queryNewPostDraftsQuery.data || queryEditPostDraftsQuery.data) {
    let drafts;
    if (isEdit) {
      drafts = queryEditPostDraftsQuery.data || [];
    } else {
      drafts = queryNewPostDraftsQuery.data || [];
    }

    return (
      <div className="row">
        <div className="col">
          {drafts.length > 0 && (
            <div className="overflow-y-auto">
              <div className="list-group">
                {drafts.map((item) => {
                  return (
                    <div
                      key={item.id}
                      className={classNames(
                        'card border text-muted border-1 mb-3 list-group-item list-group-item-action cursor-pointer',
                        currentItemId === item.id ? 'active' : null,
                      )}
                      title={`${item.createdOn} - ${
                        item.name || item.overview
                      }`}
                      onClick={onClickItem.bind(this, item)}
                    >
                      <div className="card-body px-0 py-2">
                        <div className="row">
                          <div className="col-3 m-auto text-center ms-0">
                            <i
                              className={classNames(
                                'bi bi-compass fs-2',
                                currentItemId === item.id
                                  ? 'text-white'
                                  : 'text-secondary',
                              )}
                            ></i>
                          </div>
                          <div className="col-8 align-self-center">
                            {item.name && (
                              <p className="card-text mb-2">
                                <small
                                  className={classNames(
                                    currentItemId === item.id
                                      ? 'text-white'
                                      : 'text-muted',
                                  )}
                                >
                                  {item.name || ''}
                                </small>
                              </p>
                            )}

                            <p
                              className={classNames(
                                'card-title mb-0 text-truncate',
                                currentItemId === item.id
                                  ? 'text-white'
                                  : 'text-secondary',
                              )}
                            >
                              <time dateTime={item.createdOn}>
                                {formatTime(item.createdOn)}
                              </time>
                            </p>
                          </div>
                        </div>
                      </div>
                    </div>
                  );
                })}
              </div>
            </div>
          )}

          {drafts.length === 0 && <Alert message={t('noDraft')} />}
        </div>

        {currentItem && (
          <div className="col-12 overflow-hidden my-4">
            <Item
              drafts={drafts}
              queryKey={isEdit ? editPostQueryKey : newPostQueryKey}
              currentItem={currentItem}
              setCurrentItem={setCurrentItem}
              hideModal={hideModal}
              setData={setData}
            />
          </div>
        )}
      </div>
    );
  }

  if (queryNewPostDraftsQuery.error || queryEditPostDraftsQuery.error) {
    let error;
    if (isEdit) {
      error = queryNewPostDraftsQuery.error;
    } else {
      error = queryEditPostDraftsQuery.error;
    }

    return <Alert type="error" message={error} />;
  }

  return <AlertLoad />;
}

const Item = ({
  drafts,
  queryKey,
  currentItem,
  setCurrentItem,
  hideModal,
  setData,
}: {
  drafts: IDraft[];
  queryKey: QueryKey;
  currentItem: IDraft;
  setCurrentItem: Dispatch<SetStateAction<IDraft | undefined>>;
  hideModal: () => void;
  setData: (value: any) => void;
}) => {
  const { show } = useToast();
  const queryClient = useQueryClient();
  const [isRemoveALl, setIsRemoveALl] = useState(false);
  const t = useTranslations('PostEditPage');

  const queryDraftQuery = useQuery(
    ['/forum', '/drafts', currentItem.id],
    async (context) => {
      return (await queryDraft({
        id: context.queryKey[2] + '',
      })) as IDraft;
    },
  );

  const removeDraftMutation = useMutation(async (variables: TBody<void>) => {
    await removeDraft(variables);
  });

  function onClickResumeDraft() {
    const data = queryDraftQuery.data;
    if (!data) {
      show({
        type: 'DANGER',
        message: t('dataDoesNotExist'),
      });
      return;
    }

    setData({
      name: data.name || '',
      overview: data.overview || '',
      content: data.content || '',
    });

    setCurrentItem(undefined);
    show({
      type: 'PRIMARY',
      message: t('restoreDraftCompleted'),
    });
  }

  async function onClickRemoveDraft() {
    try {
      await removeDraftMutation.mutateAsync({
        id: currentItem.id + '',
      });

      await queryClient.refetchQueries({ queryKey }, { throwOnError: true });
      setCurrentItem(undefined);
      show({
        type: 'SUCCESS',
        message: t('deleteDraftCompleted'),
      });
    } catch (e) {
      removeDraftMutation.reset();
      show({
        type: 'DANGER',
        message: e,
      });
    }
  }

  async function onClickOneRemoveDraft() {
    try {
      show({
        type: 'PRIMARY',
        message: t('deletingAllDraftsPleaseWait'),
      });

      setIsRemoveALl(true);
      await Promise.all(
        drafts.map((value) =>
          removeDraftMutation.mutateAsync({
            id: value.id + '',
          }),
        ),
      );

      await queryClient.refetchQueries({ queryKey }, { throwOnError: true });

      setCurrentItem(undefined);
      setIsRemoveALl(false);
      show({
        type: 'SUCCESS',
        message: t('deleteAllCompleted'),
      });

      hideModal();
    } catch (e) {
      setIsRemoveALl(false);
      show({
        type: 'DANGER',
        message: e,
      });
    }
  }

  if (queryDraftQuery.data) {
    const data = queryDraftQuery.data;

    return (
      <div className="row">
        <div className="col">
          <div className="vstack gap-4">
            <div className="hstack flex-wrap align-items-center gap-2">
              <div>
                <button
                  disabled={isRemoveALl}
                  className="btn btn-danger"
                  onClick={onClickOneRemoveDraft}
                >
                  {isRemoveALl ? (
                    <span
                      className="spinner-border spinner-border-sm me-2"
                      role="status"
                      aria-hidden="true"
                    ></span>
                  ) : (
                    <i className="bi bi-trash me-2"></i>
                  )}
                  {t('deleteAll')}
                </button>
              </div>
              <div>
                <button
                  disabled={!isRemoveALl && removeDraftMutation.isLoading}
                  className="btn btn-danger"
                  onClick={onClickRemoveDraft}
                >
                  {!isRemoveALl && removeDraftMutation.isLoading ? (
                    <span
                      className="spinner-border spinner-border-sm me-2"
                      role="status"
                      aria-hidden="true"
                    ></span>
                  ) : (
                    <i className="bi bi-trash me-2"></i>
                  )}
                  {t('delete')}
                </button>
              </div>
              <div>
                <button
                  className="btn btn-primary"
                  onClick={onClickResumeDraft}
                >
                  <i className="bi bi-box-arrow-in-left me-2"></i>
                  {t('restore')}
                </button>
              </div>
            </div>

            <div className="text-muted form-text">
              <i className="bi bi-info-circle me-2"></i>
              {t('clickingRestoreWillReplaceCurrentEditingContent')}
            </div>

            {data.name && (
              <div className="card">
                <div className="card-header">{t('title')}</div>
                <div className="card-body">
                  <div>{data.name}</div>
                </div>
              </div>
            )}

            {data.overview && (
              <div className="card">
                <div className="card-header">{t('overview')}</div>
                <div className="card-body">
                  <div
                    dangerouslySetInnerHTML={{ __html: data.overview }}
                  ></div>
                </div>
              </div>
            )}

            {data.content && (
              <div className="card">
                <div className="card-header">{t('content')}</div>
                <div className="card-body overflow-hidden">
                  <div
                    className="clearfix text-break content-layer"
                    dangerouslySetInnerHTML={{ __html: data.content }}
                  ></div>
                </div>
              </div>
            )}
          </div>
        </div>
      </div>
    );
  }

  if (queryDraftQuery.error) {
    return <Alert type="error" message={queryDraftQuery.error} />;
  }

  return <AlertLoad />;
};
